package sanduche.controllers;

import java.util.List;

import models.ActorColegio;
import models.Colegio;
import models.Coordinador;
import models.EscalaNotas;
import models.Grado;
import models.Materia;
import models.MateriaGrado;
import models.MateriaGradoId;
import models.Orientador;
import models.Profesor;
import models.Secretario;
import play.db.jpa.Transactional;
import sanduche.play.shared.ModuleConfig;
import sanduche.play.shared.RequestBody;
import sanduche.play.shared.RequestMethod;
import sanduche.play.shared.Route;
import sanduche.play.shared.UrlParam;
import services.ColegioProcessSrv;
import services.ColegioSrv;
import services.DAO;

@ModuleConfig(prefix = "/api/supadmin")
public class SupadminController {

	@Transactional
	@Route(value = "/go_next/:idColegio", method = RequestMethod.POST, iteratedClass = String.class)
	public static List<String> goNext(@UrlParam("idColegio") Long idColegio)
			throws InstantiationException, IllegalAccessException {
		Colegio c = ColegioSrv.getColegio(idColegio);
		// FIXME TODO FIXME TODO FIXME TODO
		List<String> s = ColegioProcessSrv.goNext(c);
		return s;
	}

	@Transactional(readOnly = true)
	@Route(value = "/colegio", method = RequestMethod.GET, iteratedClass = Colegio.class)
	public static List<Colegio> getColegios() {

		return ColegioSrv.getColegios();
	}

	@Transactional(readOnly = true)
	@Route(value = "/colegio/:idColegio", method = RequestMethod.GET)
	public static Colegio getColegio(@UrlParam("idColegio") Long idColegio) {

		return ColegioSrv.getColegio(idColegio);
	}

	@Transactional
	@Route(value = "/colegio", method = RequestMethod.POST)
	public static Colegio newColegio(@RequestBody Colegio c)
			throws InstantiationException, IllegalAccessException {

		DAO.persist(c);
		DAO.flush();
		ColegioProcessSrv.startProcess(c);
		return c;
	}

	@Transactional
	@Route(value = "/colegio/:idColegio", method = RequestMethod.PUT)
	public static void updateColegio(@RequestBody Colegio c,
			@UrlParam("idColegio") Long idColegio)
			throws InstantiationException, IllegalAccessException {
		c.setId(idColegio);
		DAO.merge(c);
		DAO.flush();
	}

	@Transactional(readOnly = true)
	@Route(value = "/profesor", method = RequestMethod.GET, iteratedClass = Profesor.class)
	public static List<Profesor> getProfesores(
			@UrlParam("idColegio") Long idColegio) {

		return (List<Profesor>) getActores(Profesor.class, idColegio);
	}

	@Transactional(readOnly = true)
	@Route(value = "/orientador", method = RequestMethod.GET, iteratedClass = Orientador.class)
	public static List<Orientador> getOrientadores(
			@UrlParam("idColegio") Long idColegio) {

		return (List<Orientador>) getActores(Orientador.class, idColegio);
	}

	@Transactional(readOnly = true)
	@Route(value = "/secretario", method = RequestMethod.GET, iteratedClass = Secretario.class)
	public static List<Secretario> getSecretarios(
			@UrlParam("idColegio") Long idColegio) {

		return (List<Secretario>) getActores(Secretario.class, idColegio);
	}

	@Transactional(readOnly = true)
	@Route(value = "/coordinador", method = RequestMethod.GET, iteratedClass = Coordinador.class)
	public static List<Coordinador> getCoordinadores(
			@UrlParam("idColegio") Long idColegio) {

		return (List<Coordinador>) getActores(Coordinador.class, idColegio);
	}

	private static List<? extends ActorColegio> getActores(
			Class<? extends ActorColegio> clazz,
			@UrlParam("idColegio") Long idColegio) {
		return DAO.query(clazz, -1, "idColegio", idColegio);
	}

	@Transactional
	@Route(value = "/profesor", method = RequestMethod.POST)
	public static Profesor newProfesor(@RequestBody Profesor c,
			@UrlParam("idColegio") Long idColegio) {

		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);

		return c;
	}

	@Transactional
	@Route(value = "/orientador", method = RequestMethod.POST)
	public static Orientador newOrientador(@RequestBody Orientador c,
			@UrlParam("idColegio") Long idColegio) {

		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);
		return c;
	}

	@Transactional
	@Route(value = "/secretario", method = RequestMethod.POST)
	public static Secretario newSecretario(@RequestBody Secretario c,
			@UrlParam("idColegio") Long idColegio) {

		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);
		return c;
	}

	@Transactional
	@Route(value = "/coordinador", method = RequestMethod.POST)
	public static Coordinador newCoordinador(@RequestBody Coordinador c,
			@UrlParam("idColegio") Long idColegio) {

		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);
		return c;
	}

	@Transactional
	@Route(value = "/materia", method = RequestMethod.POST)
	public static Materia newMateriaColegio(@RequestBody Materia mc) {

		DAO.persist(mc);
		DAO.flush();
		return mc;
	}

	@Transactional
	@Route(value = "/grado", method = RequestMethod.POST)
	public static Grado newGradoColegio(@RequestBody Grado mc) {
		DAO.persist(mc);
		DAO.flush();
		return mc;
	}

	@Transactional
	@Route(value = "/materia/:idMateria", method = RequestMethod.DELETE)
	public static void deleteMateriaColegio(
			@UrlParam("idMateria") Long idMateria,
			@UrlParam("idColegio") Long idColegio) {
		Materia mc = DAO.find(Materia.class, idMateria);
		if (mc != null && mc.getIdColegio() == idColegio)
			DAO.remove(mc);
	}

	@Transactional
	@Route(value = "/grado/:idGrado", method = RequestMethod.DELETE)
	public static void deleteGradoColegio(@UrlParam("idGrado") Long idGrado,
			@UrlParam("idColegio") Long idColegio) {
		Grado mc = DAO.find(Grado.class, idGrado);
		if (mc != null && mc.getIdColegio() == idColegio)
			DAO.remove(mc);

	}

	@Transactional(readOnly = true)
	@Route(value = "/materia", method = RequestMethod.GET, iteratedClass = Materia.class)
	public static List<Materia> getMateriasColegio(
			@UrlParam("idColegio") Long idColegio) {
		return ColegioSrv.getMateriasColegio(idColegio);
	}

	@Transactional(readOnly = true)
	@Route(value = "/grado", method = RequestMethod.GET, iteratedClass = Grado.class)
	public static List<Grado> getGradosColegio(
			@UrlParam("idColegio") Long idColegio) {
		return ColegioSrv.getGradosColegio(idColegio);
	}

	@Transactional(readOnly = true)
	@Route(value = "/grado/:idGrado", method = RequestMethod.GET)
	public static Grado getGrado(@UrlParam("idGrado") Long idGrado) {
		return DAO.find(Grado.class, idGrado);
	}

	@Transactional(readOnly = true)
	@Route(value = "/materia/:idMateria", method = RequestMethod.GET)
	public static Materia getMateria(@UrlParam("idMateria") Long idMateria) {
		return DAO.find(Materia.class, idMateria);
	}

	@Transactional
	@Route(value = "/grado/:idGrado", method = RequestMethod.PUT)
	public static void updateGrado(@RequestBody Grado g,
			@UrlParam("idGrado") Long idGrado) {
		DAO.merge(g);
	}

	@Transactional
	@Route(value = "/materia/:idMateria", method = RequestMethod.PUT)
	public static void updateMateria(@RequestBody Materia m,
			@UrlParam("idMateria") Long idMateria) {
		DAO.merge(m);
	}

	@Transactional(readOnly = true)
	@Route(value = "/materia", method = RequestMethod.GET, iteratedClass = Materia.class)
	public static List<Materia> getMateriasGrado(
			@UrlParam("idGrado") Long idGrado,
			@UrlParam("idColegio") Long idColegio) {
		List<Materia> m = DAO
				.execute(
						"SELECT mc FROM Materia m, MateriaGrado mc WHERE mc.idMateria=m.id AND mc.idGrado=:idGrado AND mc.idColegio=:idColegio",
						-1, "idGrado", idGrado, "idColegio", idColegio);
		return m;
	}

	@Transactional
	@Route(value = "/materia_grado", method = RequestMethod.POST)
	public static MateriaGrado newMateriaGrado(@RequestBody MateriaGrado mc) {
		DAO.merge(mc);
		return mc;
	}

	@Transactional
	@Route(value = "/materia_grado/:idMateria/:idGrado", method = RequestMethod.DELETE)
	public static void deleteMateriaGrado(
			@UrlParam("idMateria") Long idMateria,
			@UrlParam("idGrado") Long idGrado,
			@UrlParam("idColegio") Long idColegio) {
		MateriaGrado mc = DAO.find(MateriaGrado.class, new MateriaGradoId(
				idMateria, idColegio, idGrado));
		if (mc != null)
			DAO.remove(mc);

	}

	@Transactional
	@Route(value = "/escala_notas/:idColegio", method = RequestMethod.GET)
	public static EscalaNotas getEscalaNotas(
			@UrlParam("idColegio") Long idColegio) {
		return DAO.find(EscalaNotas.class, idColegio);
	}

	@Transactional
	@Route(value = "/escala_notas/:idColegio", method = RequestMethod.PUT)
	public static EscalaNotas setEscalaNotas(@RequestBody EscalaNotas en,
			@UrlParam("idColegio") Long idColegio) {

		en.setIdColegio(idColegio);
		DAO.merge(en);
		DAO.flush();
		return en;
	}

}
